/*
* Copyright (c) Microsoft Corporation.  All Rights Reserved.
*
* Class containing the necessary information used to resolve Detour filters.
*/
#pragma once
#include "Mock10.h"
#include "Functor.h"
#include "ParameterValueTraits.h"

#pragma push_macro("SEALED")
#undef SEALED

#if _MSC_VER >= 1400
# define SEALED sealed
#else
# define SEALED
#endif

namespace Mock10 { namespace Private
{
    class DetourFunctionBase;
    
    struct __declspec(novtable) DetourFilterInfoBase abstract
    {
        DetourFilterInfoBase(const DetourFunctionBase& detourFunction, const void* pReturnAddress)
        : m_detourFunction(detourFunction)
        , m_pReturnAddress(pReturnAddress)
        {
        }

        virtual ParameterValue GetParameterValue(unsigned long parameterIndex) const = 0;

        const DetourFunctionBase& m_detourFunction;
        const void* m_pReturnAddress;

    private:
        DetourFilterInfoBase(const DetourFilterInfoBase&); // Non-implemented
        const DetourFilterInfoBase& operator =(const DetourFilterInfoBase&); // Non-implemented
    };

    template <typename TPrototype>
    struct DetourFilterInfo SEALED : public DetourFilterInfoBase
    {
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter1>::Result Parameter1;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter2>::Result Parameter2;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter3>::Result Parameter3;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter4>::Result Parameter4;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter5>::Result Parameter5;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter6>::Result Parameter6;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter7>::Result Parameter7;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter8>::Result Parameter8;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter9>::Result Parameter9;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter10>::Result Parameter10;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter11>::Result Parameter11;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter12>::Result Parameter12;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter13>::Result Parameter13;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter14>::Result Parameter14;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter15>::Result Parameter15;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter16>::Result Parameter16;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter17>::Result Parameter17;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter18>::Result Parameter18;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter19>::Result Parameter19;
        typedef typename WEX::Common::MakeReference<typename WEX::Common::Functor<TPrototype>::Parameter20>::Result Parameter20;

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress)
        : DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1)
        : m_p1(p1)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2)
        : m_p1(p1)
        , m_p2(p2)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15, Parameter16 p16)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , m_p16(p16)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15, Parameter16 p16, Parameter17 p17)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , m_p16(p16)
        , m_p17(p17)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15, Parameter16 p16, Parameter17 p17, Parameter18 p18)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , m_p16(p16)
        , m_p17(p17)
        , m_p18(p18)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15, Parameter16 p16, Parameter17 p17, Parameter18 p18, Parameter19 p19)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , m_p16(p16)
        , m_p17(p17)
        , m_p18(p18)
        , m_p19(p19)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        DetourFilterInfo(const DetourFunctionBase& detourFunction, const void* pReturnAddress, Parameter1 p1, Parameter2 p2, Parameter3 p3, Parameter4 p4,
                         Parameter5 p5, Parameter6 p6, Parameter7 p7, Parameter8 p8, Parameter9 p9, Parameter10 p10, Parameter11 p11, Parameter12 p12,
                         Parameter13 p13, Parameter14 p14, Parameter15 p15, Parameter16 p16, Parameter17 p17, Parameter18 p18, Parameter19 p19, Parameter20 p20)
        : m_p1(p1)
        , m_p2(p2)
        , m_p3(p3)
        , m_p4(p4)
        , m_p5(p5)
        , m_p6(p6)
        , m_p7(p7)
        , m_p8(p8)
        , m_p9(p9)
        , m_p10(p10)
        , m_p11(p11)
        , m_p12(p12)
        , m_p13(p13)
        , m_p14(p14)
        , m_p15(p15)
        , m_p16(p16)
        , m_p17(p17)
        , m_p18(p18)
        , m_p19(p19)
        , m_p20(p20)
        , DetourFilterInfoBase(detourFunction, pReturnAddress)
        {
        }

        ParameterValue GetParameterValue(unsigned long parameterIndex) const
        {
            switch (parameterIndex)
            {
            case 0:
                return ParameterValueTrait<Parameter1>::GetValue(m_p1);
                break;

            case 1:
                return ParameterValueTrait<Parameter2>::GetValue(m_p2);
                break;

            case 2:
                return ParameterValueTrait<Parameter3>::GetValue(m_p3);
                break;

            case 3:
                return ParameterValueTrait<Parameter4>::GetValue(m_p4);
                break;

            case 4:
                return ParameterValueTrait<Parameter5>::GetValue(m_p5);
                break;

            case 5:
                return ParameterValueTrait<Parameter6>::GetValue(m_p6);
                break;

            case 6:
                return ParameterValueTrait<Parameter7>::GetValue(m_p7);
                break;

            case 7:
                return ParameterValueTrait<Parameter8>::GetValue(m_p8);
                break;

            case 8:
                return ParameterValueTrait<Parameter9>::GetValue(m_p9);
                break;

            case 9:
                return ParameterValueTrait<Parameter10>::GetValue(m_p10);
                break;

            case 10:
                return ParameterValueTrait<Parameter11>::GetValue(m_p11);
                break;

            case 11:
                return ParameterValueTrait<Parameter12>::GetValue(m_p12);
                break;

            case 12:
                return ParameterValueTrait<Parameter13>::GetValue(m_p13);
                break;

            case 13:
                return ParameterValueTrait<Parameter14>::GetValue(m_p14);
                break;

            case 14:
                return ParameterValueTrait<Parameter15>::GetValue(m_p15);
                break;

            case 15:
                return ParameterValueTrait<Parameter16>::GetValue(m_p16);
                break;

            case 16:
                return ParameterValueTrait<Parameter17>::GetValue(m_p17);
                break;

            case 17:
                return ParameterValueTrait<Parameter18>::GetValue(m_p18);
                break;

            case 18:
                return ParameterValueTrait<Parameter19>::GetValue(m_p19);
                break;

            case 19:
                return ParameterValueTrait<Parameter20>::GetValue(m_p20);
                break;
            }

            return ParameterValue();
        }

    private:
        DetourFilterInfo(const DetourFilterInfo&);
        const DetourFilterInfo& operator =(const DetourFilterInfo&);

        Parameter1 m_p1;
        Parameter2 m_p2;
        Parameter3 m_p3;
        Parameter4 m_p4;
        Parameter5 m_p5;
        Parameter6 m_p6;
        Parameter7 m_p7;
        Parameter8 m_p8;
        Parameter9 m_p9;
        Parameter10 m_p10;
        Parameter11 m_p11;
        Parameter12 m_p12;
        Parameter13 m_p13;
        Parameter14 m_p14;
        Parameter15 m_p15;
        Parameter16 m_p16;
        Parameter17 m_p17;
        Parameter18 m_p18;
        Parameter19 m_p19;
        Parameter20 m_p20;
    };
} /* namespace Private */ } /* namespace Mock10 */

#pragma pop_macro("SEALED")